﻿
Namespace MVVM

    Public Class EditFormViewBase
        Inherits UserControl

#Region " Declarations "

        Private _objErrorEventRoutedEventHandler As RoutedEventHandler

#End Region

#Region " Methods "

        Private Sub ExceptionValidationErrorHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)

            Dim args As System.Windows.Controls.ValidationErrorEventArgs = DirectCast(e, System.Windows.Controls.ValidationErrorEventArgs)

            If TypeOf args.Error.RuleInError Is System.Windows.Controls.ExceptionValidationRule Then

                Dim objEditFormViewModelBase As EditFormViewModelBase = TryCast(Me.DataContext, EditFormViewModelBase)

                If objEditFormViewModelBase IsNot Nothing Then

                    'we only want to work with validation errors that are Exceptions because the business object has already recorded the business rule violations using IDataErrorInfo.
                    Dim objBindingExpression As BindingExpression = DirectCast(args.Error.BindingInError, System.Windows.Data.BindingExpression)
                    Dim strDataItemName As String = objBindingExpression.DataItem.ToString
                    Dim strPropertyName As String = objBindingExpression.ParentBinding.Path.Path
                    Dim sb As New System.Text.StringBuilder(1024)

                    For Each objVE As ValidationError In System.Windows.Controls.Validation.GetErrors(DirectCast(args.OriginalSource, DependencyObject))

                        If TypeOf objVE.RuleInError Is System.Windows.Controls.ExceptionValidationRule Then
                            sb.AppendFormat("{0} has error ", strPropertyName)

                            If objVE.Exception Is Nothing OrElse objVE.Exception.InnerException Is Nothing Then
                                sb.AppendLine(objVE.ErrorContent.ToString)

                            Else
                                sb.AppendLine(objVE.Exception.InnerException.Message)
                            End If

                        End If

                    Next

                    If args.Action = ValidationErrorEventAction.Added Then
                        objEditFormViewModelBase.AddUIValidationError(New UIValidationError(strDataItemName, strPropertyName, sb.ToString))

                    ElseIf args.Action = ValidationErrorEventAction.Removed Then
                        objEditFormViewModelBase.RemoveUIValidationError(New UIValidationError(strDataItemName, strPropertyName, sb.ToString))

                    Else
                        'this can only happen if the .NET Framework changes.  Better to put a sanity check in now that have a very hard to find bug later.
                        Throw New ArgumentOutOfRangeException("Action", args.Action, "Action value was not programmed.")
                    End If

                End If

            End If

        End Sub

        Private Sub UserControlBase_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
            'this adds a form level handler and will listen for each control that has the NotifyOnValidationError=True and a ValidationError occurs.
            _objErrorEventRoutedEventHandler = New RoutedEventHandler(AddressOf ExceptionValidationErrorHandler)
            Me.AddHandler(System.Windows.Controls.Validation.ErrorEvent, _objErrorEventRoutedEventHandler, True)
        End Sub

        Private Sub UserControlBase_Unloaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Unloaded
            Me.RemoveHandler(System.Windows.Controls.Validation.ErrorEvent, _objErrorEventRoutedEventHandler)
            _objErrorEventRoutedEventHandler = Nothing
        End Sub

#End Region

    End Class

End Namespace
